package com.clinic.logic.drug;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.clinic.accessor.db.DrugAccessor;
import com.clinic.accessor.db.DrugBrandAccessor;
import com.clinic.accessor.db.DrugStockAccessor;
import com.clinic.entity.db.Drug;
import com.clinic.entity.db.DrugBrand;
import com.clinic.entity.db.DrugStock;
import com.clinic.entity.gui.GuiDrug;
import com.clinic.entity.gui.GuiDrugBrand;
import com.clinic.entity.gui.GuiPagination;
import com.clinic.entity.param.Index;
import com.clinic.util.CommonUtil;
import com.clinic.util.ConvertUtil;

@Component
public class DrugLogic {
	
	@Autowired
	private DrugBrandAccessor drugBrandAccessor;
	@Autowired
	private DrugAccessor drugAccessor;
	@Autowired
	private DrugStockAccessor drugStockAccessor;
	
	@Transactional
	public GuiDrug getDrugDetailsById(long id) {
		Drug drug = drugAccessor.getDrugById(id);
		GuiDrug guiDrug = ConvertUtil.getGuiDrugByDrug(drug);
		guiDrug.setBrand(ConvertUtil.getGuiDrugBrandByDrugBrand(drug.getBrand()));
		return guiDrug;
	}
	
	public int getDrugStockCount(long id) {
		List<DrugStock> drugStocks = drugStockAccessor.getDrugStocksByDrugId(id, new Index());
		int count = 0;
		for (DrugStock drugstock : drugStocks) {
			count = count + drugstock.getStockAmount();
		}
		return count;
	}
	
	public void deleteDrugDetailsById(long id) {
		Drug drug = drugAccessor.getDrugById(id);
		if (drug != null) {
			// TODO delete other related data before ... appointments, contacts... etc
			drug.setBrand(null);
			drugAccessor.delete(drug);
		}
	}
	
	public boolean isNotValidDrugInsert(GuiDrug guiDrug) {
		
		return !isValidDrugInsert(guiDrug);
	}
	
	public boolean isValidDrugInsert(GuiDrug guiDrug) {
		
		String name = guiDrug.getName();
		Drug result = drugAccessor.getDrugByName(name);
		return (result == null);
	}
	
	public boolean isValidWeight(GuiDrug guiDrug) {	
		return (guiDrug.getWeight() > 0);
	}
	
	public boolean isValidMinimum(GuiDrug guiDrug) {	
		return (guiDrug.getMinimum() > 0);
	}
	
	@Transactional
	public List<GuiDrug> getDrugsAchiveMinimum(Index index) {
		// TODO: write a inner query
		List<Drug> drugList = drugAccessor.getDrugs(index);
		List<GuiDrug> result = new ArrayList<>();
		for (Drug drug : drugList) {
			int totalStockAmount = 0;
			List<DrugStock> stocks = drug.getStocks();
			for (DrugStock drugStock : stocks) {
				totalStockAmount += drugStock.getStockAmount();
			}
			if (drug.getMinimum() >= totalStockAmount) {
				GuiDrug guiDrug = ConvertUtil.getGuiDrugByDrug(drug);
				guiDrug.setTotalStockCount(totalStockAmount);
				result.add(guiDrug);
			}
		}
		return result;
	}

	public GuiDrug updateDrug(GuiDrug guiDrug) {
		Drug drug = drugAccessor.getDrugById(guiDrug.getDrugId());
		Drug oDrug = ConvertUtil.getDrugByGuiDrug(guiDrug, drug);
		DrugBrand brand = drugBrandAccessor.getDrugBrandById(guiDrug.getBrand().getBrandId());
		oDrug.setBrand(brand);
		Drug mDrug = drugAccessor.insertOrUpdate(oDrug);
		GuiDrug result = ConvertUtil.getGuiDrugByDrug(mDrug);
		GuiDrugBrand fBrand = ConvertUtil.getGuiDrugBrandByDrugBrand(mDrug.getBrand());
		result.setBrand(fBrand);
		return result;
	}
	
	@Transactional
	public boolean isValidDrugUpdate(GuiDrug guiDrug) {
		long drugId = guiDrug.getDrugId();
		Drug oDrug = drugAccessor.getDrugById(drugId);
		String nDrugName = guiDrug.getName();
		String oDrugName = oDrug.getName();
		Drug uDrug = drugAccessor.getDrugByName(nDrugName);	

		return ((nDrugName.equals(oDrugName)) || (uDrug == null));
	}
	
	public GuiDrug insertDrug(GuiDrug guiDrug) {
		Drug drug = ConvertUtil.getDrugByGuiDrug(guiDrug);
		DrugBrand drugBrand = drugBrandAccessor.getDrugBrandById(guiDrug.getBrand().getBrandId());
		drug.setBrand(drugBrand);
		
		Drug result = drugAccessor.insertOrUpdate(drug);
		return ConvertUtil.getGuiDrugByDrug(result);
	}
	
	@Transactional
	public List<GuiDrug> getDrugListByTerm(String term, String column, Index index) {
		List<Drug> drugList = drugAccessor.getOrderedDrugsByTerm(term, column, index);		
		return getGuiDrugsByDrugs(drugList);
	}
	
	@Transactional
	public List<GuiDrug> getDrugList(Index index) {
		List<Drug> drugList = drugAccessor.getDrugs(index);
		return getGuiDrugsByDrugs(drugList);
	}
	
	public GuiPagination getPaginationOfDrugsByTerm(String term, String column, int page) {
		int total = drugAccessor.countOfOrderedDrugsByTerm(term, column);
		return CommonUtil.getPaginationInfo(page, total);
	}
	
	public GuiPagination getPaginationOfDrugs(int page) {
		int total = drugAccessor.countOfDrugs();
		return CommonUtil.getPaginationInfo(page, total);
	}

	private List<GuiDrug> getGuiDrugsByDrugs(List<Drug> drugList) {
		List<GuiDrug> result = new ArrayList<>();
		for (Drug drug : drugList) {
			GuiDrug guiDrug = ConvertUtil.getGuiDrugByDrug(drug);
			guiDrug.setTotalStockCount(getDrugStockCount(guiDrug.getDrugId()));
			guiDrug.setBrand(ConvertUtil.getGuiDrugBrandByDrugBrand(drug.getBrand()));
			if (guiDrug.isAvailable()) {
				result.add(guiDrug);
			}
		}
		return result;
	}
	
}
